﻿#include "FITKAbaMeshPartVTK.h"
#include "FITK_Interface/FITKInterfaceModel/FITKElementFactory.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"

namespace Interface
{
    /**
     * @brief 建立单元类型映射
     * @author LiBaojun (libaojunqd@foxmail.com)
     * @date 2024-03-30
     */
    static const QHash<FITKAbaMeshPartVTK::AbaEleType, FITKModelEnum::FITKEleType>  AbaElementTypeHash =
    {
        { FITKAbaMeshPartVTK::AbaEleType::B31, FITKModelEnum::FITKEleType::Line2 },
        { FITKAbaMeshPartVTK::AbaEleType::B32, FITKModelEnum::FITKEleType::Line3 },
        { FITKAbaMeshPartVTK::AbaEleType::T3D2, FITKModelEnum::FITKEleType::Line2 },
        { FITKAbaMeshPartVTK::AbaEleType::T3D3, FITKModelEnum::FITKEleType::Line3 },
        { FITKAbaMeshPartVTK::AbaEleType::S3, FITKModelEnum::FITKEleType::Tri3 },
        { FITKAbaMeshPartVTK::AbaEleType::CPS3, FITKModelEnum::FITKEleType::Tri3 },
        { FITKAbaMeshPartVTK::AbaEleType::S4, FITKModelEnum::FITKEleType::Quad4 },
        { FITKAbaMeshPartVTK::AbaEleType::S4R, FITKModelEnum::FITKEleType::Quad4 },
        { FITKAbaMeshPartVTK::AbaEleType::S8, FITKModelEnum::FITKEleType::Quad8 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D4, FITKModelEnum::FITKEleType::Tet4 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D10, FITKModelEnum::FITKEleType::Tet10 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D10M, FITKModelEnum::FITKEleType::Tet10 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D6, FITKModelEnum::FITKEleType::Wedge6 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D8, FITKModelEnum::FITKEleType::Hex8 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D8I, FITKModelEnum::FITKEleType::Hex8 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D8R, FITKModelEnum::FITKEleType::Hex8 },
        { FITKAbaMeshPartVTK::AbaEleType::C3D20, FITKModelEnum::FITKEleType::Hex20 },
        { FITKAbaMeshPartVTK::AbaEleType::R3D4, FITKModelEnum::FITKEleType::Quad4 },


    };
 


    FITKAbaMeshPartVTK::~FITKAbaMeshPartVTK()
    {
    }

    bool FITKAbaMeshPartVTK::appendElement(AbaEleType eleType, const int eleID, const QList<int>& nodeIDList)
    {
        //创建单元
        Interface::FITKAbstractElement* ele = this->createElement(eleType);
        //错误判断
        if (ele == nullptr) return false;
        if (ele->getNodeCount() != nodeIDList.size()) 
        {
            delete ele; 
            return false;
        }
        //设置节点与ID
        ele->setNodeID(nodeIDList);
        ele->setEleID(eleID);
        //追加单元
        FITKUnstructuredMeshVTK::appendElement(ele);
        //记录单元类型
        _elementTypes.append(eleType);
        return true;
    }


    FITKAbaMeshPartVTK::AbaEleType FITKAbaMeshPartVTK::getAbaElementType(const int index) const
    {
        //错误判断
        if (index < 0 || index >= _elementTypes.size()) return AbaEleType::AbaEleNone;
        return _elementTypes.at(index);
    }
     
    FITKAbaMeshPartVTK::AbaEleType FITKAbaMeshPartVTK::getAbaElementTypeByID(const int eleid) const
    {
        const int  index = this->getEleIndexByID(eleid);
        return this->getAbaElementType(index);
    }

    Interface::FITKAbstractElement* FITKAbaMeshPartVTK::createElement(AbaEleType abaEleType)
    {
        if (!AbaElementTypeHash.contains(abaEleType)) return nullptr;
        FITKModelEnum::FITKEleType eleType = AbaElementTypeHash[abaEleType];
        //从工厂创建
        return Interface::FITKElementFactory:: createElement(eleType);
    }


    AbaEleSurface FITKAbaMeshPartVTK::getEleFace(const int cellid, FITKAbaSurfaceLabel::AbaSurfLabel label)
    {
        AbaEleSurface face;

        //获取单元与单元类型
        const int eleIndex = this->getEleIndexByID(cellid);
        AbaEleType eletype = this->getAbaElementType(eleIndex);
        FITKAbstractElement* ele = this->getElementAt(eleIndex);
        if (ele == nullptr) return face;
        //获取表面标记对应的单元表面索引
        int faceIndex = -1;
        face._faceType = FITKAbaSurfaceLabel::GetFaceVtkType(eletype, label, faceIndex);
        if (faceIndex < 0) return face;
        //从单元中获取节点id
        face._nodeIDs = ele->getFace(faceIndex);
        return face;
    }

}
